package fr.idak.sring.tiles.generic.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import fr.idak.spring.tiles.util.Loggable;

@Transactional
public class GenericDaoHibernateImpl<T, PK extends Serializable>  implements GenericDao<T, PK> {

	protected Class<T> entityClass;
	@Loggable
	private Logger LOGGER;
	
	@Autowired
	protected SessionFactory sessionFactory;
	
	/**
	 * recherche de la classe à initialiser
	 */
	@SuppressWarnings("unchecked")
	public GenericDaoHibernateImpl() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass()
             .getGenericSuperclass();
        this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
    }
	
	@SuppressWarnings("unchecked")
	public T create(T object) {
		return (T) getCurentSession().merge(object);
	}

	@SuppressWarnings("unchecked")
	public T read(PK id) {
		return (T) getCurentSession().get(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	public T update(T object) {
		return (T) getCurentSession().save(object);
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll() {
		String query = "from "+this.entityClass.getName();
		return (List<T>) getCurentSession().createQuery(query).list();
	}

	public void delete(T object) {
		getCurentSession().delete(object);
	}
	
	public int count() {
		Criteria criteria = this.sessionFactory.getCurrentSession().createCriteria(entityClass);
		return ((Number)criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
	}
	
	private Session getCurentSession(){
		return this.sessionFactory.getCurrentSession();
	}


}
